use anyhow::{anyhow, Result};
use std::path::PathBuf;
use toml_edit::{Array, DocumentMut, InlineTable, Value};

fn make_value(on: &str, run: &str, desc: &str) -> Result<Value> {
    let mut table = InlineTable::new();
    let mut array = Array::new();
    //将on的每个字符转换为字符串并推入数组
    for c in on.chars() {
        array.push(Value::from(c.to_string()));
    }
    table.insert("on", Value::from(array));
    table.insert("run", Value::from(run));
    table.insert("desc", Value::from(desc));
    table.decor_mut().set_prefix("\r\n\t");
    Ok(Value::InlineTable(table))
}

fn modify_keymap(doc: &mut DocumentMut, on: &str, run: &str, desc: &str) -> Result<()> {
    let keymap_array = doc
        .get_mut("manager")
        .and_then(|v| v.get_mut("keymap"))
        .and_then(|v| v.as_array_mut())
        .ok_or(anyhow!("未找到keymap数组"))?;

    for item in keymap_array.iter_mut() {
        if let Some(table) = item.as_inline_table_mut() {
            if let Some(Value::Array(existing_on)) = table.get("on") {
                let existing_on_str: String =
                    existing_on.iter().filter_map(|v| v.as_str()).collect();

                if existing_on_str == on {
                    // 找到匹配的快捷键，更新run和desc
                    table.insert("run", Value::from(run));
                    table.insert("desc", Value::from(desc));
                    return Ok(());
                }
            }
        }
    }

    // 如果没有找到匹配的快捷键，添加新的
    let new_key = make_value(on, run, desc)?;
    keymap_array.push_formatted(new_key);
    Ok(())
}

fn get_dir() -> Result<String> {
    let dir = std::env::current_dir()?;
    Ok(dir.to_string_lossy().to_string())
}

fn get_on() -> Result<String> {
    //命令行程序的第1个参数为on
    let on = std::env::args().nth(1).ok_or(anyhow!("未找到on参数"))?;
    Ok(on)
}

fn run() -> Result<()> {
    //从环境变量读取
    let dir = PathBuf::from(std::env::var("YAZI_DIR")?);
    let keymap_path = dir.join("keymap.toml");
    let toml_str = std::fs::read_to_string(&keymap_path)?;
    let mut doc = toml_str.parse::<DocumentMut>()?;
    let dst_dir = get_dir()?;
    let on = get_on()?;
    // 将dst_dir中的\\替换为/
    let dst_dir = dst_dir.replace("\\", "/");
    let run = format!("cd \"{}\"", dst_dir);
    let desc = format!("go to {}", dst_dir);
    modify_keymap(&mut doc, &on, &run, &desc)?;
    let toml_str = doc.to_string();
    std::fs::write(keymap_path, toml_str)?;
    Ok(())
}

fn main() -> Result<()> {
    run()
}
